package org.NooLab.glue.instances;

import java.util.Vector;

import org.NooLab.glue.components.pkg.TaskPackage;
import org.NooLab.glue.subscription.FilterPackageIntf;
import org.NooLab.glue.subscription.FuturesIntf;
import org.NooLab.glue.transaction.Transaction;
import org.NooLab.glue.transaction.Transactions;
import org.NooLab.utilities.timing.DelayFor;
import org.NooLab.utilities.timing.DelayNotificationIntf;


/**
 * 
 * RECEPTORS are instances for high(er)-level perception, according to the terminology
 * coined by Douglas Hofstadter;
 *  
 * 
 * 
 * 
 * 
 * TODO   avoid shutdown after shutdown request from MessageBoard, if
 * 			- a process is running, and processes should be completed (default) 
 * 			- the receptor never should shut down
 * 
 */
class ReceptorParticipant 	extends 
										MessageBoardParticipant 
							implements
										ParticipantReceptorIntf, 
										DelayNotificationIntf {

	// ParticipantFactory factory;
	TaskPackage taskPackage;
	TaskPackage resultPackage;

	FilterPackageIntf subscriptionFilter;
	
	
	DelayFor processSimulation ;
	
	long transactID;
	boolean transactionCanceled=false;
	

	double lastperc;
	long lastFeedbackTime = System.currentTimeMillis();

	public ReceptorParticipant(ParticipantFactory pfac, String mbconfigpath, String name) {
		super(mbconfigpath, name);

		factory = pfac;

		// resultPackage = new TaskPackage();

	}

	@Override
	public TaskPackage getResultPackage() {

		resultPackage = new TaskPackage();

		return resultPackage;
	}

	@Override
	public TaskPackage digestingReceivedMsg(TaskPackage taskPackage) {

		out.printErr(4, "ParticipantFactory :: ReceptorParticipant :: digestingReceivedMsg()");

		factory.taskDeliveryStation.taskProvider(taskPackage);

		out.print(4,"ParticipantFactory :: ReceptorParticipant :: digestingReceivedMsg() -> leaving...");
				
			
		return resultPackage;
	}
	
	@Override
	public TaskPackage digestingReceivedMsg(Vector<TaskPackage> taskPackages) {
		return null;
	}


	@Override
	public void connect() {

		connect(participantsRole, false);
		factory.connected = true;

	}
 


	@Override
	public void sendTaskCompletionStateMsg(long transactionID, double percentage) {

		
		getMrd().sendTaskCompletionStateMsg(transactionID, percentage);
	}

	@Override
	public void disconnect() {

		stop();
	}
 

	/**
	 * for state messages issued by the MessageBoard or the SOURCE while the
	 * instance is working
	 */
	@Override
	public void currentStateMessage(String str) {
		// overrides the abstract method from class MessageBoardParticipant
		factory.taskDeliveryStation.interControlMessage(str);
	}

	 

	@Override  // callback locked into "processSimulation{}" = DelayFor()
	public void setPercentageOfWaitingTime(double perc) {
		long now = System.currentTimeMillis();

		if ((perc - lastperc >= 5.0) || (now - lastFeedbackTime > 300000)) {
			sendTaskCompletionStateMsg(transactID, perc);
			lastperc = perc;
			lastFeedbackTime = now;
		}
		out.print(4, "   --- receptor process time : ");
	}

	public void startProcessNotification(long transactID) {

		try{
			
			this.transactID = transactID;
			sendTaskCompletionStateMsg(transactID, 0.1);
			lastperc=0;
			
			processSimulation = (new DelayFor(this));
			processSimulation.period(20000, 20, 0); // 0=relative ->20=percentage of totalTime
			 
			processSimulation.setUserbreak(true) ;
			processSimulation = null;

			setPercentageOfWaitingTime(99.9);
			
			
		}catch(Exception e){
			e.printStackTrace();
		}
		
		// breaks the total waiting time into parts, in order to allow for
		// interrupting the waiting time
	}

	public void handlingCancelRequest( TaskPackage taskPackage , int marker){
		 
		 
		
		
		// canceling transaction
		long transactionID ;
		
		transactionID = taskPackage.getTransactionID() ;
		
		xRegistration.getTasksBeingCanceled().add(transactionID) ;

		if (marker==1){
			out.printErr(2, "Request received for canceling transaction "+transactionID);
			processSimulation.setUserbreak(true);
		}
		
		
		transactionCanceled = true;

		// accessing the accessible client		
		((TaskReceiverIntf)(factory.parent)).handlingControlRequest( transactionID, "cancel" ) ;

	}

	
	public int getTransactionControlState() {
		int state = 0;
		
		if (transactionCanceled){
			state = Transaction.TS_TASK_CANCELED ;
			
		}
		
		return state;
	}


	public void subscribe() {
		FilterPackageIntf filter;
		// subscriptionFilter = filter;
		// here we should create a new object of the same type , 
		// instead of referring to the object which is hosted by ??
		
 	}

	
	@Override
	public FuturesIntf getFutures() {
		
		return getFutures(0);
	}
 
	@Override
	public FuturesIntf getFutures(int mode) {
		FuturesIntf futures ;
		
		futures = super.getFutures(mode);
		 
		return futures;
	}


 

	
} // ReceptorParticipant

